home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / system-config-printer / probe_printer.py < prev    next >
Text File  |  2009-10-19  |  8KB  |  275 lines

  1. ## system-config-printer
  2.  
  3. ## Copyright (C) 2006, 2007, 2008, 2009 Red Hat, Inc.
  4. ## Copyright (C) 2006 Florian Festi <ffesti@redhat.com>
  5. ## Copyright (C) 2007, 2008, 2009 Tim Waugh <twaugh@redhat.com>
  6.  
  7. ## This program is free software; you can redistribute it and/or modify
  8. ## it under the terms of the GNU General Public License as published by
  9. ## the Free Software Foundation; either version 2 of the License, or
  10. ## (at your option) any later version.
  11.  
  12. ## This program is distributed in the hope that it will be useful,
  13. ## but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. ## GNU General Public License for more details.
  16.  
  17. ## You should have received a copy of the GNU General Public License
  18. ## along with this program; if not, write to the Free Software
  19. ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21. import cupshelpers
  22. from debug import *
  23. import socket, time
  24. import gtk
  25. from timedops import TimedOperation
  26. import subprocess
  27.  
  28. def wordsep (line):
  29.     words = []
  30.     escaped = False
  31.     quoted = False
  32.     in_word = False
  33.     word = ''
  34.     n = len (line)
  35.     for i in range (n):
  36.         ch = line[i]
  37.         if escaped:
  38.             word += ch
  39.             escaped = False
  40.             continue
  41.  
  42.         if ch == '\\':
  43.             in_word = True
  44.             escaped = True
  45.             continue
  46.  
  47.         if in_word:
  48.             if quoted:
  49.                 if ch == '"':
  50.                     quoted = False
  51.                 else:
  52.                     word += ch
  53.             elif ch.isspace ():
  54.                 words.append (word)
  55.                 word = ''
  56.                 in_word = False
  57.             elif ch == '"':
  58.                 quoted = True
  59.             else:
  60.                 word += ch
  61.         else:
  62.             if ch == '"':
  63.                 in_word = True
  64.                 quoted = True
  65.             elif not ch.isspace ():
  66.                 in_word = True
  67.                 word += ch
  68.  
  69.     if word != '':
  70.         words.append (word)
  71.  
  72.     return words
  73.  
  74. ### should be ['network', 'foo bar', ' ofoo', '"', '2 3']
  75. ##print wordsep ('network "foo bar" \ ofoo "\\"" 2" "3')
  76.  
  77. class LpdServer:
  78.     def __init__(self, hostname):
  79.         self.hostname = hostname
  80.         self.max_lpt_com = 8
  81.  
  82.     def _open_socket(self):
  83.         port = 515
  84.         try:
  85.             host, port = self.hostname.split(":", 1)
  86.         except ValueError:
  87.             host = self.hostname
  88.         
  89.         s = None
  90.         try:
  91.             ai = socket.getaddrinfo(host, port, socket.AF_UNSPEC,
  92.                                     socket.SOCK_STREAM)
  93.         except socket.gaierror:
  94.             ai = []
  95.  
  96.         for res in ai:
  97.             af, socktype, proto, canonname, sa = res
  98.             try:
  99.                 s = socket.socket(af, socktype, proto)
  100.                 s.settimeout(0.5)
  101.             except socket.error, msg:
  102.                 s = None
  103.                 continue
  104.             try:
  105.                 s.connect(sa)
  106.             except socket.error, msg:
  107.                 s.close()
  108.                 s = None
  109.                 continue
  110.             break
  111.         return s
  112.  
  113.     def probe_queue(self,name, result):
  114.         s = self._open_socket()
  115.         if not s: return False
  116.         print name
  117.         
  118.         try:
  119.             s.send('\2%s\n' % name) # cmd send job to queue
  120.             data = s.recv(1024) # receive status
  121.             print repr(data)
  122.         except socket.error, msg:
  123.             print msg
  124.             try:
  125.                 s.close ()
  126.             except:
  127.                 pass
  128.  
  129.             return False
  130.  
  131.         if len(data)>0 and ord(data[0])==0:
  132.             try:
  133.                 s.send('\1\n') # abort job again
  134.                 s.close ()
  135.             except:
  136.                 pass
  137.  
  138.             result.append(name)
  139.             return True
  140.  
  141.         try:
  142.             s.close()
  143.         except:
  144.             pass
  145.  
  146.         return False
  147.  
  148.     def get_possible_queue_names (self):
  149.         candidate = ["PASSTHRU", "ps", "lp", "PORT1", ""]
  150.         for nr in range (self.max_lpt_com):
  151.             candidate.extend (["LPT%d" % nr,
  152.                                "LPT%d_PASSTHRU" % nr,
  153.                                "COM%d" % nr,
  154.                                "COM%d_PASSTHRU" % nr])
  155.         for nr in range (50):
  156.             candidate.append ("pr%d" % nr)
  157.  
  158.         return candidate
  159.  
  160.     def probe(self):
  161.         result = []
  162.         for name in self.get_possible_queue_names ():
  163.             while gtk.events_pending ():
  164.                 gtk.main_iteration ()
  165.  
  166.             found = self.probe_queue(name, result)
  167.             if not found and name.startswith ("pr"):
  168.                 break
  169.             time.sleep(0.1) # avoid DOS and following counter measures 
  170.  
  171.         return result
  172.  
  173. class PrinterFinder:
  174.     def find (self, hostname, callback_fn):
  175.         self.hostname = hostname
  176.         self.callback_fn = callback_fn
  177.         op = TimedOperation (self._do_find)
  178.  
  179.     def _do_find (self):
  180.         self._cached_attributes = dict()
  181.         for fn in [self._probe_snmp,
  182.                    self._probe_lpd,
  183.                    self._probe_hplip]:
  184.             try:
  185.                 fn ()
  186.             except Exception, e:
  187.                 nonfatalException ()
  188.  
  189.         # Signal that we've finished.
  190.         self.callback_fn (None)
  191.  
  192.     def _probe_snmp (self):
  193.         # Run the CUPS SNMP backend, pointing it at the host.
  194.         null = file ("/dev/null", "r+")
  195.         try:
  196.             p = subprocess.Popen (args=["/usr/lib/cups/backend/snmp",
  197.                                         self.hostname],
  198.                                   stdin=null,
  199.                                   stdout=subprocess.PIPE,
  200.                                   stderr=null)
  201.         except OSError, e:
  202.             if e == errno.ENOENT:
  203.                 return
  204.  
  205.             raise
  206.  
  207.         (stdout, stderr) = p.communicate ()
  208.         if p.returncode != 0:
  209.             return
  210.  
  211.         for line in stdout.split ('\n'):
  212.             words = wordsep (line)
  213.             n = len (words)
  214.             if n == 5:
  215.                 (device_class, uri, make_and_model, info, device_id) = words
  216.             elif n == 4:
  217.                 (device_class, uri, make_and_model, info) = words
  218.             else:
  219.                 continue
  220.  
  221.             device_dict = { 'device-class': device_class,
  222.                             'device-make-and-model': make_and_model,
  223.                             'device-info': info }
  224.             if n == 5:
  225.                 device_dict['device-id'] = device_id
  226.  
  227.             device = cupshelpers.Device (uri, **device_dict)
  228.             self.callback_fn (device)
  229.  
  230.             # Cache the make and model for use by other search methods
  231.             # that are not able to determine it.
  232.             self._cached_attributes['device-make-and-model'] = make_and_model
  233.  
  234.     def _probe_lpd (self):
  235.         lpd = LpdServer (self.hostname)
  236.         for name in lpd.get_possible_queue_names ():
  237.             found = lpd.probe_queue (name, [])
  238.             if found:
  239.                 uri = "lpd://%s/%s" % (self.hostname, name)
  240.                 device_dict = { 'device-class': 'network',
  241.                                 'device-info': self.hostname }
  242.                 device_dict.update (self._cached_attributes)
  243.                 new_device = cupshelpers.Device (uri, **device_dict)
  244.                 self.callback_fn (new_device)
  245.  
  246.             if not found and name.startswith ("pr"):
  247.                 break
  248.  
  249.             time.sleep(0.1) # avoid DOS and following counter measures 
  250.  
  251.     def _probe_hplip (self):
  252.         null = file ("/dev/null", "r+")
  253.         try:
  254.             p = subprocess.Popen (args=["hp-makeuri", "-c", self.hostname],
  255.                                   stdin=null,
  256.                                   stdout=subprocess.PIPE,
  257.                                   stderr=null)
  258.         except OSError, e:
  259.             if e == errno.ENOENT:
  260.                 return
  261.  
  262.             raise
  263.  
  264.         (stdout, stderr) = p.communicate ()
  265.         if p.returncode != 0:
  266.             return
  267.  
  268.         uri = stdout.strip ()
  269.         if uri.find (":") != -1:
  270.             device_dict = { 'device-class': 'network',
  271.                             'device-info': uri }
  272.             device_dict.update (self._cached_attributes)
  273.             new_device = cupshelpers.Device (uri, **device_dict)
  274.             self.callback_fn (new_device)
  275.